//循环数组实现的阻塞队列，m_back=(m_back+1)%m_max_size
//线程安全，每个操作前都先加互斥锁，操作完成后解锁

#ifndef BLOCK_QUEUE_H
#define BLOCK_QUEUE_H

#include<iostream>
#include<stdlib.h>
#include<pthread.h>
#include<sys/time.h>
#include"../lock/locker.h"
using namespace std;

template<typename T>
class block_queue{
public:
    //构造函数
    block_queue(int max_size=1000){
        if(max_size<=0){
            exit(1);
        }
        m_max_size=max_size;
        m_array=new T[max_size];
        m_size=0;
        m_front=-1;
        m_back=-1;
    }

    //清空函数
    void clear(){
        m_mutex.lock();
        m_size=0;
        m_front=-1;
        m_back=-1;
        m_mutex.unlock();
    }

    //析构函数
    ~block_queue(){
        m.mutex.lock();
        if(m_array!=NULL){
            delete[] m_array;
        }
        m_mutex.unlock();
    }

    //判满
    bool full(){
        m_mutex.lock();
        if(m_size>=m_max_size){
            m_mutex.unlock();
            return true;
        }
        m_mutex.unlock();
        return false;
    }

    bool empty(){
        m_mutex.lock();
        if(m_size==0){
            m_mutex.unlock();
            return true;
        }
        m_mutex.unlock();
        return false;
    }

    bool front(T&value){
        m_mutex.lock();
        if(0==m_size){
            m_mutex.unlock();
            return false;
        }
        value=m_array[m_front];
        m_mutex.unlock();
        return true;
    }

    bool back(T&value){
        m_mutex.lock();
        if(0==m_size){
            m_mutex.unlock();
            return false;
        }
        value=m_array[m_back];
        m_mutex.unlock();
        return true;
    }

    int size(){
        int temp=0;
        m_mutex.lock();
        temp=m_size;
        m_mutex.unlock();
        return temp;
    }

    int max_size(){
        int temp=0;
        m_mutex.lock();
        temp=m_max_size;
        m_mutex.unlock();
        return temp;
    }
    
    //向队列添加元素，需要将所有使用队列的线程先唤醒
    //若有元素push进队列，相当于生产者生产了一个元素
    //若当前没有线程等待条件变量，则唤醒无意义
    bool push(const T&item){
        m_mutex.lock();
        if(m_size>=m_max_size){
            m.cond.broadcast();
            m_mutex.unlock();
            return false;
        }
        m_back=(m_back+1)%m_max_size;
        m_array[m_back]=item;
        m_size++;
        m_cond.broadcast();
        m_mutex.unlock();
        return true;
    }
private:
    locker m_mutex;
    cond m_cond;

    T*m_array;
    int m_size;
    int m_max_size;
    int m_front;
    int m_back;
};

#endif